/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.mall.util.jsp.ImportTag
   Module Description   :

   Date Created      : 2010/1/7
   Original Author   : andy.chuang
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.mall.util.jsp;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * @author andy.chuang
 * 
 */
public class ImportTag extends BodyTagSupport {

	/**
     * 
     */
	private static final long serialVersionUID = 3682690788219329700L;
	private static Logger LOGGER = LoggerFactory.getLogger(ImportTag.class);
	private boolean enableCache = true;
	//    private String cacheType="file";
	//    private int timeout=-1;
	private String appendParameter;
	private String key;
	private String url;
	private String surfix;

	/**
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * @param url the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
		String uri = null;
		if (url.indexOf("?") > 0) {
			uri = url.substring(0, url.indexOf("?"));
		} else {
			uri = url;
		}
		if (uri.indexOf(".") > 0) {
			surfix = uri.substring(uri.indexOf(".") + 1, uri.length());
		}
	}

	/**
	 * @return the enableCache
	 */
	public boolean isEnableCache() {
		return enableCache;
	}

	/**
	 * @param enableCache the enableCache to set
	 */
	public void setEnableCache(boolean enableCache) {
		this.enableCache = enableCache;
	}

	/**
	 * @return the appendParameter
	 */
	public String getAppendParameter() {
		return appendParameter;
	}

	/**
	 * @param appendParameter the appendParameter to set
	 */
	public void setAppendParameter(String appendParameter) {
		this.appendParameter = appendParameter;
	}

	/**
	 * @return the key
	 */
	public String getKey() {
		return key;
	}

	/**
	 * @param key the key to set
	 */
	public void setKey(String key) {
		this.key = key;
	}

	@Override
	public int doStartTag() throws JspException {
		return EVAL_BODY_BUFFERED;
	}

	@Override
	public int doAfterBody() throws JspException {
		return EVAL_BODY_INCLUDE;
	}

	@Override
	public int doEndTag() throws JspException {
		WebApplicationContext wc = WebApplicationContextUtils.getWebApplicationContext(pageContext.getServletContext());
		JspCacheManager jspCacheManager = (JspCacheManager) wc.getBean("jspCacheManager");
		if (jspCacheManager == null) {
			LOGGER.error("jspCacheManager must to be set in spring context!!");
		}
		String resetCache = this.pageContext.getRequest().getParameter("resetCache");
		if (resetCache == null) {
			resetCache = "false";
		}
		if (enableCache) {
			File file = jspCacheManager.getContent(key, url, appendParameter, pageContext.getRequest().getParameterMap());
			if (!file.exists() || resetCache.equals("true")) {
				String content = evaluateJsp();
				if (surfix != null && !surfix.equals("htm") && !surfix.equals("html") && !surfix.equals("jsp")) {
					InputStream is = new ByteArrayInputStream(content.getBytes());
					try {
						writeContent(is);
					} catch (Exception e) {
						LOGGER.warn("display static html failed!!html abs path:" + file.getAbsolutePath());
					}
				}
				jspCacheManager
						.addCache(jspCacheManager.getKey(key, url, appendParameter, pageContext.getRequest().getParameterMap()), content);
			} else {
				try {
					InputStream is = new FileInputStream(file);
					writeContent(is);
				} catch (Exception e) {
					LOGGER.warn("display static html failed!!html abs path:" + file.getAbsolutePath());
				}
			}
		} else {
			String content = evaluateJsp();
			InputStream is = new ByteArrayInputStream(content.getBytes());
			try {
				writeContent(is);
			} catch (Exception e) {
				LOGGER.error("display static html failed!!");
			}
		}
		return EVAL_PAGE;
	}

	private void writeContent(InputStream is) throws Exception {
		Reader reader = new InputStreamReader(is, "UTF-8");
		BufferedReader br = new BufferedReader(reader);
		StringBuffer sb = new StringBuffer();
		int i;

		// under JIT, testing seems to show this simple loop is as fast
		// as any of the alternatives
		while ((i = br.read()) != -1) {
			sb.append((char) i);
		}
		is.close();
		reader.close();
		pageContext.getOut().print(sb.toString());
	}

	private String evaluateJsp() {
		String content = null;
		String fullUrl = null;
		if (surfix != null && !surfix.equals("htm") && !surfix.equals("html") && !surfix.equals("jsp")) {
			try {
				BufferedReader br = null;
				fullUrl = "http://localhost:" + pageContext.getRequest().getServerPort() + pageContext.getServletContext().getContextPath()
						+ url;

				URL oURL = new URL(new String(fullUrl));

				br = new BufferedReader(new InputStreamReader(oURL.openStream(), "UTF-8"));
				String line = "";
				StringBuffer requestString = new StringBuffer("");
				while ((line = br.readLine()) != null) {
					requestString.append(line);
				}
				content = requestString.toString();
				br.close();
			} catch (Exception e) {
				LOGGER.warn(" load url failed!! url:" + fullUrl);
				e.printStackTrace();
			}

		} else {
			try {
				RequestDispatcher rd = pageContext.getServletContext().getRequestDispatcher(url);
				ImportResponseWrapper irw = new ImportResponseWrapper((HttpServletResponse) pageContext.getResponse());

				rd.include(pageContext.getRequest(), irw);

				content = irw.getString();
			} catch (Exception e) {
				LOGGER.error("evalute jsp failed!! url:" + url);
			}
		}
		return content;
	}

}
